1. Regressão Logística com Regularização

Nesta parte do trabalho, será implementada a Regressão Logística Regularizada para prever se os microchips de uma usina de fabricação passam na garantia de qualidade (QA). Durante a QA, cada microchip passa por vários testes para garantir se está funcionando corretamente. Dessa forma, a Gestão de Produto da fábrica terá o resultados de teste para alguns microchips em dois testes diferentes.

A partir desses dois testes, será determinado se os microchips deveriam ser aceitos ou rejeitados. Para auxiliar a tomar a decisão, há um conjunto de dados com resultados de testes anteriores sobre microchips, a partir do qual é possível construir um modelo de Regressão Logística.

O arquivo $ex2data2.txt$ contém os dados a serem usados nessa parte do trabalho. A primeira coluna corresponde aos resultados do primeiro teste, enquanto que a segunda coluna corresponde aos resultados do segundo teste. A terceira coluna contém os valores da classe (y = 0 significa rejeitado no teste, e y = 1 significa aceito no teste).

1.1 Visualização dos Dados

Para a maioria dos conjuntos de dados do mundo real, não é possível criar um gráfico para visualizar seus pontos. Mas, para o conjunto de dados fornecido, isso é possível. Implemente um script em Python que produza um gráfico de dispersão (scatter plot) dos dados fornecidos. Após finalizado, seu script deve produzir um resultado similar ao apresentado na Figura abaixo.


In [83]:
import os 
import pandas as pd
import numpy as np
import matplotlib as plt

from numpy import loadtxt, zeros, ones, array, linspace, logspace
from pylab import scatter, show, legend, xlabel, ylabel

%matplotlib inline

In [110]:
# Construindo um dataset com base num Dataframe, já identificando colunas e exibindo seus primeiros 20 registros.
df = pd.read_csv('am-T2-dados/ex2data2.txt', names=['QATest1', 'QATest2', 'QAcceptance'])
df.head()


Out[110]:
QATest1 QATest2 QAcceptance
0 0.051267 0.69956 1
1 -0.092742 0.68494 1
2 -0.213710 0.69225 1
3 -0.375000 0.50219 1
4 -0.513250 0.46564 1

In [111]:
# Visualização da Distribuição dos Dados conforme Histograma

df.hist()
plt.pyplot.show()

df.QATest1.hist(), df.QATest2.hist(), df.QAcceptance.hist()
plt.pyplot.show()



In [112]:
df.describe()


Out[112]:
QATest1 QATest2 QAcceptance
count 118.000000 118.000000 118.000000
mean 0.054779 0.183102 0.491525
std 0.496654 0.519743 0.502060
min -0.830070 -0.769740 0.000000
25% -0.372120 -0.254385 0.000000
50% -0.006336 0.213455 0.000000
75% 0.478970 0.646562 1.000000
max 1.070900 1.108900 1.000000

In [113]:
df.QATest1.describe().round(2)


Out[113]:
count    118.00
mean       0.05
std        0.50
min       -0.83
25%       -0.37
50%       -0.01
75%        0.48
max        1.07
Name: QATest1, dtype: float64

In [114]:
df.QATest2.describe().round(2)


Out[114]:
count    118.00
mean       0.18
std        0.52
min       -0.77
25%       -0.25
50%        0.21
75%        0.65
max        1.11
Name: QATest2, dtype: float64

In [115]:
df.QAcceptance.describe().round(2)


Out[115]:
count    118.00
mean       0.49
std        0.50
min        0.00
25%        0.00
50%        0.00
75%        1.00
max        1.00
Name: QAcceptance, dtype: float64

In [116]:
# Gráfico de correlação entre População e Lucro
positive = df[df['QAcceptance'].isin([1])]  
negative = df[df['QAcceptance'].isin([0])]

figura, grafico = plt.pyplot.subplots(figsize=(10,6))  
grafico.scatter(positive['QATest1'], positive['QATest2'], c='xkcd:black', marker='+', label='Accepted')  
grafico.scatter(negative['QATest1'], negative['QATest2'], c='xkcd:yellow', marker='o', label='Rejected')  
grafico.legend()  
grafico.set_xlabel('Microchip Test1')  
grafico.set_ylabel('Microchip Test2');


1.2 Mapeamento de características (feature mapping)

Uma maneira de tornar os dados mais apropriados para a classificação é criar mais características a partir das já existentes. Para isso, você deve criar uma função mapFeature. Essa função deve ser implementada em um arquivo de nome mapFeature.py, que irá mapear as características para todos os termos polinomiais de x1 e x2, até a sexta potência. Como resultado desse mapeamento, nosso vetor de duas características (os escores nos dois testes de QA) será transformado em um vetor de 28 dimensões.

Um classificador que usa regressão logística treinado nesse vetor de características de maior dimensão terá uma fronteira de decisão mais complexa e parecerá não-linear quando desenhado em um gráfico bidimensional.

Embora o mapeamento de características nos permita construir um classificador mais expressivo, também é mais suscetível a sobreajuste (overfitting). Desse modo, será implementada a Regressão Logística Regularizada sobre os dados fornecidos e também verá como a regularização pode ajudar a combater o problema do sobreajuste.


In [117]:
#def mapFeature(X) :
#    '''
#    Função de mapeamento das características
#    '''
#    potencia = 6
#    Xf = X
#    
#    X1 = Xf['QATest1']  
#    X2 = Xf['QATest2']
#
#    Xf.insert(3, 'Ones', 1)
#
#    for i in range(potencia+1):  
#        for j in range(i+1):
#            Xf['F' + str(i) + str(j)] = np.power(X1, i-j) * np.power(X2, j)
#
#    Xf.drop('QATest1', axis=1, inplace=True)  
#    Xf.drop('QATest2', axis=1, inplace=True)
#
#    return Xf

In [129]:
def mapFeature(X1, X2) :
    '''
    Função que mapeia características p/ os termos polinomiais X1 e X2 até a 6ª potência.
    Retorna um novo conjunto com mais características, através do algoritmo de mapping
    X1, X2, X1 ** 2, X2 ** 2, X1*X2, X1*X2 ** 2, etc...
    Os parâmetros X1, X2 devem ser do mesmo tamanho
    '''
    # Potência padrão para o mapeamento
    potencia = 6
    
    X1.shape = (X1.size, 1)
    X2.shape = (X2.size, 1)
    
    features = np.ones(shape=(X1.size, 1))

    for i in range(1, potencia + 1):
        for j in range(i + 1):
            r = (X1 ** (i - j)) * (X2 ** j)
            features = np.append(features, r, axis=1)

    return features

In [130]:
df.QATest1.size


Out[130]:
118

In [131]:
dfeature = mapFeature(df.QATest1, df.QATest2)
dfeature.describe()


---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/anaconda/lib/python3.6/site-packages/pandas/core/generic.py in __setattr__(self, name, value)
   3000                 else:
-> 3001                     object.__setattr__(self, name, value)
   3002             except (AttributeError, TypeError):

AttributeError: can't set attribute

During handling of the above exception, another exception occurred:

AttributeError                            Traceback (most recent call last)
<ipython-input-131-a3c4a7020a28> in <module>()
----> 1 dfeature = mapFeature(df.QATest1, df.QATest2)
      2 dfeature.describe()

<ipython-input-129-db2cb02719b5> in mapFeature(X1, X2)
      9     potencia = 6
     10 
---> 11     X1.shape = (X1.size, 1)
     12     X2.shape = (X2.size, 1)
     13 

/anaconda/lib/python3.6/site-packages/pandas/core/generic.py in __setattr__(self, name, value)
   3001                     object.__setattr__(self, name, value)
   3002             except (AttributeError, TypeError):
-> 3003                 object.__setattr__(self, name, value)
   3004 
   3005     # ----------------------------------------------------------------------

AttributeError: can't set attribute

1.3 Função de custo e gradiente

Agora, você deverá implementar o código para calcular a função de custo e o gradiente para a regressão logística regularizada. Crie um arquivo de nome costFunctionReg.py que contém uma função de nome costFunctionReg.py e que computa o custo e o gradiente. Lembre-se de que a função de custo regularizada na regressão logística é dada por:

$$J_{regularizado} = \small \underbrace{-\frac{1}{m} \sum\limits_{i = 1}^{m} \large{(}\small y^{(i)}\log\left(x^{(i)}\right) + (1-y^{(i)})\log\left(1- x^{(i)}\right) \large{)} }_\text{Função de Custo} + \underbrace{\frac{\lambda}{2m} \sum\limits_{j = 1}^{n}\ {\theta}_{j}^{2} }_\text{Fator Regularização} $$

Depois de concluir a implementação da função costFunctionReg, você deve testar a corretude dela usando o valor inicial de ${\theta}$ (inicializado todo com zeros). Você deve ver que o custo é de cerca de 0.693. Porém, usando a função costFunctionReg, você agora deve computar os valores ótimos para ${\theta}$.


In [12]:
def sigmoid(x):
    '''
    A função sigmoid
    '''
    g = np.array([x]).flatten()
    s = 1 / (1 + np.exp(-g))
    return s

In [13]:
def costFunctionReg(theta, X, y, alpha): 
    '''
    A versão do GD que acabamos de estudar é denominada *Batch gradienteient Descent*.
    Em cada iteração do algoritmo, todo o conjunto de treinamento é utilizado.

        X = características (features)
        y = alvo (target)
        alpha = taxa de aprendizado
        regularizacao = Taxa de regularizacaoularização

    '''
    
    m = y.size
    H = sigmoid(X.dot(theta).T)
    
    J = (1/m) * np.sum( np.multiply(-y, np.log(H)) - np.multiply((1 - y), np.log(1 - H)) )
    regularizacao = (alpha/2*m) * theta**2
    
    J_regular = J + regularizacao

    parameters = theta.shape[1]
    gradiente = np.zeros(parameters)
    error = sigmoid(X * theta.T) - y

    for i in range(parameters):
        term = np.multiply(error, X[:,i])
        if (i == 0):
            gradiente[i] = np.sum(term)/m
        else:
            gradiente[i] = np.sum(term)/m + ((alpha/m) * theta[:,i])

    return J, gradiente

1.3.1 Testando a Função de Custo e o Gradiente


In [14]:
# set X and y (remember from above that we moved the label to column 0)
#df.QATest1
#df.QATest2

cols = df.shape[1]  
X2 = df.iloc[:,2]  
y2 = df.iloc[:,:2]

# convert to numpy arrays and initalize the parameter array theta
X2 = np.array(X2.values)  
y2 = np.array(y2.values)  
theta2 = np.zeros(11)

learningRate = 0.01

costFunctionReg(theta2, X2, y2, learningRate)


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-14-ed9e472432e3> in <module>()
     14 learningRate = 0.01
     15 
---> 16 costFunctionReg(theta2, X2, y2, learningRate)

<ipython-input-13-729a155474ec> in costFunctionReg(theta, X, y, alpha)
     12 
     13     m = y.size
---> 14     H = sigmoid(X.dot(theta).T)
     15 
     16     J = (1/m) * np.sum( np.multiply(-y, np.log(H)) - np.multiply((1 - y), np.log(1 - H)) )

ValueError: shapes (118,) and (11,) not aligned: 118 (dim 0) != 11 (dim 0)

1.4 Esboço da fronteira de decisão

Nessa parte, você deve esboçar (plotar) a fronteira de decisão que foi aprendida para separar os exemplos positivos dos negativos. Crie uma arquivo de nome plotDecisionBoundary.py, para criar esse gráfico que traça o limite da decisão não-linear. Seu gráfico deve ser semelhante ao apresentado na Figura abaixo.


In [15]:
#Plot Boundary
u = linspace(-1, 1.5, 50)
v = linspace(-1, 1.5, 50)
z = np.zeros(shape=(len(u), len(v)))
for i in range(len(u)):
    for j in range(len(v)):
        z[i, j] = (mapFeature(array(u[i]), array(v[j])).dot(array(theta)))

z = z.T
contour(u, v, z)
title('lambda = %f' % l)
xlabel('Microchip Test 1')
ylabel('Microchip Test 2')
legend(['y = 1', 'y = 0', 'Decision boundary'])
show()




#def plotDecisionBoundary(X, y, theta, alpha, iteracao):
#    '''
#    A versão do GD que acabamos de estudar é denominada *Batch Gradient Descent*.
#    Em cada iteração do algoritmo, todo o conjunto de treinamento é utilizado.
#
#        X = características (features)
#        y = alvo (target)
#    '''
#    
#    u = linspace(-1, 1.5, 50)
#    v = linspace(-1, 1.5, 50)
#    z = zeros(shape=(len(u), len(v)))
#    for i in range(len(u)):
#        for j in range(len(v)):
#            z[i, j] = (map_feature(array(u[i]), array(v[j])).dot(array(theta)))
#
#    z = z.T
#    contour(u, v, z)
#    title('lambda = %f' % l)
#    xlabel('Microchip Test 1')
#    ylabel('Microchip Test 2')
#    legend(['y = 1', 'y = 0', 'Decision boundary'])
#    show()


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-15-0de86676eaed> in <module>()
      7 for i in range(len(u)):
      8     for j in range(len(v)):
----> 9         z[i, j] = (mapFeature(array(u[i]), array(v[j])).dot(array(theta)))
     10 
     11 z = z.T

TypeError: mapFeature() takes 1 positional argument but 2 were given

2 Regressão Linear com Regularização

Na primeira metade desta parte, você implementará a regressão linear com regularização para prever a quantidade de água fluindo de uma barragem usando a mudança do nível da água em um reservatório. Na próxima metade, você realizará diagnósticos dos algoritmos de aprendizado por meio de depuração e irá examinar os efeitos de viés (bias) e da variância (variance).

Você irá usar o dataset fornecido no arquivo ex5data1.mat$^1$. Nesse arquivo há registros históricos na mudança no nível da água, x, e da quantidade de água que sai da barragem, y. Este conjunto de dados é dividido em três partes:

  • Um conjunto de treinamento que seu modelo aprenderá em: X, y
  • Um conjunto de validação cruzada para determinar o parâmetro de regularizacão: Xval, yval
  • Um conjunto de testes para avaliar o desempenho. Estes são exemplos que seu modelo não irá usar durante o treino: Xtest, ytest

Os nomes das variáveis contidas no arquivo ex5data1.mat são os seguintes: X, Xtest, Xval, y, ytest, yval. Você irá precisar desses nomes para carregar os dados do arquivo para usar em seus scripts em Python.


$^1$ Arquivos com a extensão .mat são normalmente criados no Octave ou no Matlab. Para carregar esse arquivo no Python, você pode usar o procedimento descrito em http://www. blogforbrains.com/blog/2014/9/6/loading-matlab-mat-data-in-python


In [16]:
# Carregando o arquivo gerado pelo MATLAB

import scipy.io
dfile = scipy.io.loadmat('am-T2-dados/ex5data1.mat')

In [ ]:

2.1 Visualização dos Dados

Você deve começar por produzir uma visualização do conjunto de dados de treinamento. O gráfico que você deve produzir deve ser similar ao apresentado na Figura abaixo:

2.2 Função de Custo de Regressão Linear Regularizada

Lembre-se de que a regressão linear regularizada tem a seguinte função de custo:

$$J_{regularizado} = \small {\frac{1}{2m} \sum\limits_{i = 1}^{m} \large{(}\small y^{(i)}\log\left(x^{(i)}\right) + (1-y^{(i)})\log\left(1- x^{(2)}\right) \large{)} } + {\frac{\lambda}{2m} \sum\limits_{j = 1}^{n}\ {\theta}_{j}^{2} } $$

Lembre-se de quê um hyperparâmetro que controla o grau de regularização (e assim, ajuda a prevenir o excesso de sobreajuste). O termo de regularização impõe uma penalidade sobre o custo total J${\theta}$. Conforme as magnitudes dos parâmetros do modelo J aumentam, a penalização aumenta também. Note que você não deve regularizar o termo ${\theta}$.

Sua tarefa é escrever uma função para calcular a função de custo da regressão linear regularizada. Você deve implementar esse código em um arquivo de nome ${linearRegCostFunction.py}$. Se possível, tente vetorizar seu código e evitar o uso de loops. Quando você tiver completado a implementação, verifique a corretude da sua função de custo usando ${\theta}$ inicializado com (1, 1). Você deve esperar ver uma saída de 303.993.

2.3 Gradiente na regressão linear regularizada

A derivada parcial do gradiente da função de custo da regressão linear regularizada é um vetor no qual o j-ésimo elemento é definido conforme a seguir:

No arquivo $linearRegCostFunction.py$, adicione código para calcular o gradiente, Quando você tiver completado essa implementação, teste a corretude usando $theta$ inicializado em (1, 1). Você deve esperar ver um gradiente de (-15.30, 598.250).

2.4 Ajustando os parâmetros da regressão linear

Nesta parte, use a função linearRegCostFunction para computar os valores ótimos para $\theta$, mas sem usar regularização, i.e., defina $\lambda$ = 0. Após isso, construa um gráfico para visualiar o modelo construído. Seu gráfico deve ser similar ao apresentado na Figura acima, referente à seção 2.1.

3 Viés-Variância

Um conceito importante no Aprendizado de Máquina é o relacionamento entre o viés (bias) e a variância (variance) de um modelo de aprendizado. Modelos com viés elevado não são suficientemente complexos para os dados e tendem a sofrer de subajuste (underfitting), enquanto que modelos com alta variância tendem a sofrer de sobreajuste.

Nesta parte do trabalho, você irá produzir gráficos dos erros de treinamento e teste na forma de curvas de aprendizado para diagnosticar problemas de viés-variância.

3.1 Curvas de Aprendizado

Agora você implementará código para gerar as curvas de aprendizado que serão úteis na depuração de algoritmos de aprendizagem. Lembre-se de que uma curva de aprendizagem traça erros de treinamento e de validação cruzada como funções do tamanho do conjunto de treinamento. Crie um arquivo de nome learningCurve.py que deve conter uma função (também chamada $learningCurve$) que retorna um vetor de erros para o conjunto de treinamento e conjunto de validação cruzada.

Para traçar a curva de aprendizado, precisamos de um conjunto de treinamento e validação cruzada erro para diferentes tamanhos de conjuntos de treinamento. Para obter diferentes tamanhos de conjuntos de treinamento, você deve usar subconjuntos diferentes do conjunto de treinamento original X. Especificamente, para um tamanho de conjunto de treinamento de $i$, você deve usar os primeiros exemplos de i (ou seja, X(1 : i; :) e y(1 : i)).

Para cada tamanho de conjunto de treinamento, você encontrar os parâmetros $\theta$. Note que o $lambda$ deve ser passado como um parâmetro para a função $learningCurve$. Depois de aprender os parâmetros $\theta$, você deve calcular o erro nos conjuntos de treinamento e de validação. Lembre-se de que o erro de treinamento para um conjunto de dados é definido como:

Em particular, note que o erro de treinamento não inclui o termo de regularização. Uma maneira de calcular o erro de treinamento é usar a sua função de custo já implementada e definir $\lambda$ = 0 apenas para calcular o erro de treinamento e o erro de validação cruzada. Quando você estiver computando o erro no conjunto de treinamento, certifique-se de computá-lo no subconjunto de treinamento (ou seja, X(1 : n; :) e y(1 : n)), em vez de usar todo o conjunto de treinamento). No entanto, para o erro de validação cruzada, você deve calculá-lo usando todo o conjunto de validação cruzada. Você deve armazenar os erros calculados em dois vetores.

Quando você estiver terminado o que foi descrito acima, imprima as curvas de aprendizado e produza um gráfico similar ao apresentado na Figura abaixo.

Na curva que você irá produzir, você poderá observar que os erros de treinamento e de validação cruzada s~ao ambos altos quando o número de exemplos de treinamento é aumentado. Isso reflete o viés alto do modelo (o modelo de regressão linear é muito simples e não consegue se ajustear bem ao conjunto de dados). Na próxima seção, você irá implementar regressão polinomial para ajustar um modelo melhor a este conjunto de dados.

4 Regressão Polinomial

O problema com nosso modelo linear é que ele é muito simples para os dados e resultou em subajuste (viés alto). Nesta parte, você irá resolver esse problema adicionando mais características. Para usar a regressão polinomial, defina uma hipótese da seguinte forma:

$$H_{\theta}(x) = \theta_{0} + \theta_{1} * waterLevel + \theta_{2} * waterLevel^{2} + ... + \theta_{p} * waterLevel^{p}$$

.

Observe que, ao definir $x_{1} = (WaterLevel)$, $x_{2} = (WaterLevel)^{2}$, ... , $x_{p} = (WaterLevel)^{p}$, obtemos um modelo de regressão linear onde os características são as diferentes pontências do valor original $(WaterLevel)$. Agora, você irá adiciona mais características usando as pontências da característica existente x no conjunto de dados. Sua tarefa nesta parte é implementar código em um arquivo de nome polyFeatures.py. Nesse arquivo, crie um função de mesmo nome que mapeie o conjunto de treinamento original X de tamanho m X 1 em suas potências mais altas. Especificamente, quando um conjunto de treinamento X de tamanho m X 1 for passado para essa função, ela deve retornar uma matriz m X p de nome X_poli, onde a coluna 1 contém os valores originais de X, a coluna 2 contém os valores de $x^{2}$, a coluna 3 contém os valores de $x^{3}$, e assim por diante. Note que você não tem que considerar a potência de expoentezero nessa função. Após implementar o descrito acima, você terá uma função que mapeia características para uma maior dimensão.


In [ ]:


In [ ]:

5 Regressão Polinomial - aprendizado

Depois de ter completado $polyFeatures.py$, você deve treinar um modelo de regressão polinomial usando sua função de custo da regressão linear. Tenha em mente que, apesar de termos termos polinomiais no vector de características, ainda estamos resolvendo um problema de otimização de regressão linear. Os termos polinomiais simplesmente se transformaram em características que podemos usar para aplicar regressão linear. Estamos usando a mesma função de custo e gradiente que você implementou para a parte anterior deste trabalho.

Para esta parte do trabalho, você usará um polinômio de grau 8. Se executarmos o treinamento diretamente sobre os dados projetados, não iremos obter um bom resultado, porque as características não irão estar na mesma escala (por exemplo, um exemplo com x = 40 agora terá uma característica $x^{8} = 40^{8} = 6.5 \times 10^{1} 2 $).

Portanto, você vai precisar aplicar a normalização de características. Portanto, antes de aprender os parâmetros $\theta$ para a regressão polinomial, você deve normalizar as características do conjunto de treinamento, e armazenar os parâmetros $\mu$ e $\sigma$. Depois de aprender os parâmetros $\theta$, você deve ver gerar dois gráficos (que devem ser similares aos das $Figuras$ abaixo) gerados com a regressão polinomial com $\lambda$ = 0.

Da Figura acima, você deve perceber que o polinômio pode se ajustar aos pontos de dados muito bem - assim, obtendo um baixo erro de treinamento. No entanto, o polinômio é muito complexo e até mesmo despenca nos extremos. Isso é um indicador de que o modelo de regressão polinomial está se ajustando demasiadamente aos dados de treinamento e que não irá generalizar bem.

Para entender melhor os problemas com o modelo não regularizado ($\lambda$ = 0), você pode ver que a curva de aprendizado (na Figura acima ) apresenta erro de treinamento baixo, mas erro de validação alto. Há uma lacuna entre os erros de treinamento e validação cruzada, indicando um problema de variância alta.

6 Tarefas adicionais (OPCIONAIS)

  • Ajuste do parâmetro de regularização. Teste o aprendizado para diferentes valores de lambda, $1 \le \lambda \le 100$. Para $\lambda = 1$, você deve ver o polinômio segue a tendência de dados bem e uma curva de aprendizado ($Figuras$ acima) mostrando que tanto o erro de validação quanto o erro de treinamento convergem para um valor relativamente baixo. Isso mostra que o modelo de regressão polinomial regularizado com $\lambda = 1$ não sofre dos problema de viés alto ou de variância alta. De fato, esse modelo alcança um bom compromisso entre viés e variância. Para $\lambda = 100$, você deve ver um polinômio ($Figura$ abaixo) que não segue os dados bem. Neste caso, há muita regularização, e o modelo é incapaz de se ajustar aos dados de treinamento.

  • Defina o valor de $\lambda$ usando o conjunto de validação. Implemente um método automatizado para selecionar o parâmetro $\lambda$. Concretamente, use um conjunto de validação cruzada para avaliar quão bom é cada valor de $\lambda$. Ao realizar essa tarefa, você deve encontrar um valor adequado de $\lambda$ em torno de 3 (veja a $Figura$ abaixo). Tente valores de $\lambda$ no intervalo $ \left[0, 0.001, 0.003, 0.01, 0.03, 0.1, 0.3, 1, 3, 10\right] $.

  • Depois de selecionar o melhor valor de $\lambda$ usando o conjunto de validação, você pode então avaliar o modelo no conjunto de teste para estimar o quão bem ele será executado em dados reais não vistos.

7 O que deve ser entregue

Você deve preparar um único relatório para a apresentar sua análise e conclusões sobre as diversas partes desse trabalho. O formato desse relatório deve ser em $PDF$. Alternativamente à entrega do relatório em $PDF$, você pode entregar um notebook $Jupyter$.

Independente de escolher entregar um relatório em $PDF$ ou na forma de um notebook $Jupyter$, entregue também todos os arquivos em Python que você criou para cada parte deste trabalho. Todos os arquivos em Python deve estar em uma única pasta.

Crie um arquivo compactado que contém o relatório (ou notebook $Jupyter$) e os arquivos ($scripts$) em Python. Esse arquivo compactado deve se chamar SEU NOME COMPLETOT1.zip. Esse arquivo compactado deve ser entregue pelo Moodle, até a data acordada.


In [ ]:

APENDICE

The standard way to avoid overfitting is called L2 regularization. It consists of appropriately modifying your cost function, from: $$J = -\frac{1}{m} \sum\limits_{i = 1}^{m} \large{(}\small y^{(i)}\log\left(a^{[L](i)}\right) + (1-y^{(i)})\log\left(1- a^{[L](i)}\right) \large{)} \tag{1}$$ To: $$J_{regularized} = \small \underbrace{-\frac{1}{m} \sum\limits_{i = 1}^{m} \large{(}\small y^{(i)}\log\left(a^{[L](i)}\right) + (1-y^{(i)})\log\left(1- a^{[L](i)}\right) \large{)} }_\text{cross-entropy cost} + \underbrace{\frac{1}{m} \frac{\lambda}{2} \sum\limits_l\sum\limits_k\sum\limits_j W_{k,j}^{[l]2} }_\text{L2 regularization cost} \tag{2}$$

Let's modify your cost and observe the consequences.

Exercise: Implement compute_cost_with_regularization() which computes the cost given by formula (2). To calculate $\sum\limits_k\sum\limits_j W_{k,j}^{[l]2}$ , use :

np.sum(np.square(Wl))

Note that you have to do this for $W^{[1]}$, $W^{[2]}$ and $W^{[3]}$, then sum the three terms and multiply by $ \frac{1}{m} \frac{\lambda}{2} $.

$\underbrace X + 1 $


In [ ]:


In [ ]: